home *** CD-ROM | disk | FTP | other *** search
/ Revista do CD-ROM 151 / cd-rom 151.iso / internet / firefox / Firefox Setup 3.0 Beta 1.exe / nonlocalized / components / nsPlacesTransactionsService.js < prev    next >
Encoding:
Text File  |  2007-11-09  |  25.4 KB  |  764 lines

  1. /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* ***** BEGIN LICENSE BLOCK *****
  3.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  4.  *
  5.  * The contents of this file are subject to the Mozilla Public License Version
  6.  * 1.1 (the "License"); you may not use this file except in compliance with
  7.  * the License. You may obtain a copy of the License at
  8.  * http://www.mozilla.org/MPL/
  9.  *
  10.  * Software distributed under the License is distributed on an "AS IS" basis,
  11.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12.  * for the specific language governing rights and limitations under the
  13.  * License.
  14.  *
  15.  * The Original Code is the Places Command Controller.
  16.  *
  17.  * The Initial Developer of the Original Code is Google Inc.
  18.  *
  19.  * Portions created by the Initial Developer are Copyright (C) 2005
  20.  * the Initial Developer. All Rights Reserved.
  21.  *
  22.  * Contributor(s):
  23.  *   Sungjoon Steve Won <stevewon@gmail.com> (Original Author)
  24.  *   Asaf Romano <mano@mozilla.com>
  25.  *
  26.  * Alternatively, the contents of this file may be used under the terms of
  27.  * either the GNU General Public License Version 2 or later (the "GPL"), or
  28.  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  29.  * in which case the provisions of the GPL or the LGPL are applicable instead
  30.  * of those above. If you wish to allow use of your version of this file only
  31.  * under the terms of either the GPL or the LGPL, and not to allow others to
  32.  * use your version of this file under the terms of the MPL, indicate your
  33.  * decision by deleting the provisions above and replace them with the notice
  34.  * and other provisions required by the GPL or the LGPL. If you do not delete
  35.  * the provisions above, a recipient may use your version of this file under
  36.  * the terms of any one of the MPL, the GPL or the LGPL.
  37.  *
  38.  * ***** END LICENSE BLOCK ***** */
  39.  
  40. const loadInSidebarAnno = "bookmarkProperties/loadInSidebar";
  41. const descriptionAnno = "bookmarkProperties/description";
  42. const CLASS_ID = Components.ID("c0844a84-5a12-4808-80a8-809cb002bb4f");
  43. const CONTRACT_ID = "@mozilla.org/browser/placesTransactionsService;1";
  44.  
  45. var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"].
  46.              getService(Components.interfaces.mozIJSSubScriptLoader);
  47. loader.loadSubScript("chrome://global/content/debug.js");
  48. loader.loadSubScript("chrome://browser/content/places/utils.js");
  49.  
  50. Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
  51.  
  52. // The minimum amount of transactions we should tell our observers to begin
  53. // batching (rather than letting them do incremental drawing).
  54. const MIN_TRANSACTIONS_FOR_BATCH = 5;  
  55.  
  56. function placesTransactionsService() {
  57.   this.mTransactionManager = Cc["@mozilla.org/transactionmanager;1"].
  58.                              createInstance(Ci.nsITransactionManager);
  59. }
  60.  
  61. placesTransactionsService.prototype = {
  62.   classDescription: "Places Transaction Manager",
  63.   classID: CLASS_ID,
  64.   contractID: CONTRACT_ID,
  65.  
  66.   QueryInterface: XPCOMUtils.generateQI([Ci.nsIPlacesTransactionsService]),
  67.  
  68.   aggregateTransactions: function placesAggrTransactions(name, transactions) {
  69.     return new placesAggregateTransactions(name, transactions);
  70.   },
  71.  
  72.   createFolder: function placesCrtFldr(aName, aContainer, aIndex,
  73.                                        aAnnotations, aChildItemsTransactions) {
  74.      return new placesCreateFolderTransactions(aName, aContainer, aIndex,
  75.                                                aAnnotations, aChildItemsTransactions);
  76.   },
  77.  
  78.   createItem: function placesCrtItem(aURI, aContainer, aIndex, aTitle,
  79.                                      aKeyword, aAnnotations, aChildTransactions) {
  80.     return new placesCreateItemTransactions(aURI, aContainer, aIndex, aTitle,
  81.                                             aKeyword, aAnnotations, aChildTransactions);
  82.   },
  83.  
  84.   createSeparator: function placesCrtSpr(aContainer, aIndex) {
  85.     return new placesCreateSeparatorTransactions(aContainer, aIndex);
  86.   },
  87.  
  88.   createLivemark: function placesCrtLivemark(aFeedURI, aSiteURI, aName,
  89.                                              aContainer, aIndex, aAnnotations) {
  90.     return new placesCreateLivemarkTransactions(aFeedURI, aSiteURI, aName,
  91.                                                 aContainer, aIndex, aAnnotations);
  92.   },
  93.  
  94.   moveItem: function placesMvItem(aItemId, aNewContainer, aNewIndex) {
  95.     return new placesMoveItemTransactions(aItemId, aNewContainer, aNewIndex);
  96.   },
  97.  
  98.   removeItem: function placesRmItem(id) {
  99.     return new placesRemoveItemTransaction(id);
  100.   },
  101.  
  102.   editItemTitle: function placesEditItmTitle(id, newTitle) {
  103.     return new placesEditItemTitleTransactions(id, newTitle);
  104.   },
  105.  
  106.   editBookmarkURI: function placesEditBkmkURI(aBookmarkId, aNewURI) {
  107.     return new placesEditBookmarkURITransactions(aBookmarkId, aNewURI);
  108.   },
  109.  
  110.   setLoadInSidebar:  function placesSetLdInSdbar(aBookmarkId, aLoadInSidebar) {
  111.     return new placesSetLoadInSidebarTransactions(aBookmarkId, aLoadInSidebar);
  112.   },
  113.  
  114.   editItemDescription: function placesEditItmDesc(aItemId, aDescription) {
  115.     return new placesEditItemDescriptionTransactions(aItemId, aDescription);
  116.   },
  117.  
  118.   editBookmarkKeyword: function placesEditBkmkKwd(id, newKeyword) {
  119.     return new placesEditBookmarkKeywordTransactions(id, newKeyword);
  120.   },
  121.  
  122.   editURIPostData: function placesEditURIPdata(aURI, aPostData) {
  123.     return new placesEditURIPostDataTransactions(aURI, aPostData);
  124.   },
  125.  
  126.   editLivemarkSiteURI: function placesEditLvmkSiteURI(folderId, uri) {
  127.     return new placesEditLivemarkSiteURITransactions(folderId, uri);
  128.   },
  129.  
  130.   editLivemarkFeedURI: function placesEditLvmkFeedURI(folderId, uri) {
  131.     return new placesEditLivemarkFeedURITransactions(folderId, uri);
  132.   },
  133.  
  134.   editBookmarkMicrosummary: function placesEditBkmkMicrosummary(aID, newMicrosummary) {
  135.     return new placesEditBookmarkMicrosummaryTransactions(aID, newMicrosummary);
  136.   },
  137.  
  138.   sortFolderByName: function placesSortFldrByName(aFolderId, aFolderIndex) {
  139.    return new placesSortFolderByNameTransactions(aFolderId, aFolderIndex);
  140.   },
  141.  
  142.   setBookmarksToolbar: function placesSetBkmkToolbar(aFolderId) {
  143.     return new placesSetBookmarksToolbarTransactions(aFolderId);
  144.   },
  145.  
  146.   commitTransaction: function placesCommitTxn(txn) {
  147.     this.mTransactionManager.doTransaction(txn);
  148.   },
  149.  
  150.   get transactionManager() {
  151.     return this.mTransactionManager;
  152.   }
  153. };
  154.  
  155. /**
  156.  * Method and utility stubs for Places Edit Transactions
  157.  */
  158. function placesBaseTransaction() {
  159. }
  160.  
  161. placesBaseTransaction.prototype = {
  162.   // for child-transactions
  163.   get wrappedJSObject() {
  164.     return this;
  165.   },
  166.  
  167.   // nsITransaction
  168.   redoTransaction: function PIT_redoTransaction() {
  169.     throw Cr.NS_ERROR_NOT_IMPLEMENTED;
  170.   },
  171.  
  172.   get isTransient() {
  173.     return false;
  174.   },
  175.  
  176.   merge: function mergeFunc(transaction) {
  177.     return false;
  178.   },
  179.  
  180.   // nsISupports
  181.   QueryInterface: XPCOMUtils.generateQI([Ci.nsITransaction]),
  182. };
  183.  
  184. function placesAggregateTransactions(name, transactions) {
  185.   this._transactions = transactions;
  186.   this._name = name;
  187.   this.container = -1;
  188.   this.redoTransaction = this.doTransaction;
  189. }
  190.  
  191. placesAggregateTransactions.prototype = {
  192.   __proto__: placesBaseTransaction.prototype,
  193.  
  194.   doTransaction: function PAT_doTransaction() {
  195.     if (this._transactions.length >= MIN_TRANSACTIONS_FOR_BATCH) {
  196.       var callback = {
  197.         _self: this,
  198.         runBatched: function() {
  199.           this._self.commit(false);
  200.         }
  201.       };
  202.       PlacesUtils.bookmarks.runInBatchMode(callback, null);
  203.     }
  204.     else
  205.       this.commit(false);
  206.   },
  207.  
  208.   undoTransaction: function PAT_undoTransaction() {
  209.     if (this._transactions.length >= MIN_TRANSACTIONS_FOR_BATCH) {
  210.       var callback = {
  211.         _self: this,
  212.         runBatched: function() {
  213.           this._self.commit(true);
  214.         }
  215.       };
  216.       PlacesUtils.bookmarks.runInBatchMode(callback, null);
  217.     }
  218.     else
  219.       this.commit(true);
  220.   },
  221.  
  222.   commit: function PAT_commit(aUndo) {
  223.     for (var i=0; i < this._transactions.length; ++i) {
  224.       var txn = this._transactions[i];
  225.       if (this.container > -1) 
  226.         txn.wrappedJSObject.container = this.container;
  227.       if (aUndo)
  228.         txn.undoTransaction();
  229.       else
  230.         txn.doTransaction();
  231.     }
  232.   }
  233. };
  234.  
  235. function placesCreateFolderTransactions(aName, aContainer, aIndex,
  236.                                         aAnnotations,
  237.                                         aChildItemsTransactions) {
  238.   this._name = aName;
  239.   this._container = aContainer;
  240.   this._index = typeof(aIndex) == "number" ? aIndex : -1;
  241.   this._annotations = aAnnotations;
  242.   this._id = null;
  243.   this._childItemsTransactions = aChildItemsTransactions || [];
  244.   this.redoTransaction = this.doTransaction;
  245. }
  246.  
  247. placesCreateFolderTransactions.prototype = {
  248.   __proto__: placesBaseTransaction.prototype,
  249.  
  250.   // childItemsTransaction support
  251.   get container() { return this._container; },
  252.   set container(val) { return this._container = val; },
  253.  
  254.   doTransaction: function PCFT_doTransaction() {
  255.     this._id = PlacesUtils.bookmarks.createFolder(this._container, 
  256.                                                   this._name, this._index);
  257.     if (this._annotations && this._annotations.length > 0)
  258.       PlacesUtils.setAnnotationsForItem(this._id, this._annotations);
  259.  
  260.     for (var i = 0; i < this._childItemsTransactions.length; ++i) {
  261.       var txn = this._childItemsTransactions[i];
  262.       txn.wrappedJSObject.container = this._id;
  263.       txn.doTransaction();
  264.     }
  265.   },
  266.  
  267.   undoTransaction: function PCFT_undoTransaction() {
  268.     PlacesUtils.bookmarks.removeFolder(this._id);
  269.     for (var i = 0; i < this._childItemsTransactions.length; ++i) {
  270.       var txn = this.childItemsTransactions[i];
  271.       txn.undoTransaction();
  272.     }
  273.   }
  274. };
  275.  
  276. function placesCreateItemTransactions(aURI, aContainer, aIndex, aTitle,
  277.                                       aKeyword, aAnnotations,
  278.                                       aChildTransactions) {
  279.   this._uri = aURI;
  280.   this._container = aContainer;
  281.   this._index = typeof(aIndex) == "number" ? aIndex : -1;
  282.   this._title = aTitle;
  283.   this._keyword = aKeyword;
  284.   this._annotations = aAnnotations;
  285.   this._childTransactions = aChildTransactions || [];
  286.   this.redoTransaction = this.doTransaction;
  287. }
  288.  
  289. placesCreateItemTransactions.prototype = {
  290.   __proto__: placesBaseTransaction.prototype,
  291.  
  292.   // childItemsTransactions support for the create-folder transaction
  293.   get container() { return this._container; },
  294.   set container(val) { return this._container = val; },
  295.  
  296.   doTransaction: function PCIT_doTransaction() {
  297.     this._id = PlacesUtils.bookmarks.insertBookmark(this.container, this._uri,
  298.                                                     this._index, this._title);
  299.     if (this._keyword)
  300.       PlacesUtils.bookmarks.setKeywordForBookmark(this._id, this._keyword);
  301.     if (this._annotations && this._annotations.length > 0)
  302.       PlacesUtils.setAnnotationsForItem(this._id, this._annotations);
  303.  
  304.     for (var i = 0; i < this._childTransactions.length; ++i) {
  305.       var txn = this._childTransactions[i];
  306.       txn.wrappedJSObject.id = this._id;
  307.       txn.doTransaction();
  308.     }
  309.   },
  310.  
  311.   undoTransaction: function PCIT_undoTransaction() {
  312.     PlacesUtils.bookmarks.removeItem(this._id);
  313.     for (var i = 0; i < this._childTransactions.length; ++i) {
  314.       var txn = this._childTransactions[i];
  315.       txn.undoTransaction();
  316.     }
  317.   }
  318. };
  319.  
  320. function placesCreateSeparatorTransactions(aContainer, aIndex) {
  321.   this._container = aContainer;
  322.   this._index = typeof(aIndex) == "number" ? aIndex : -1;
  323.   this._id = null;
  324. }
  325.  
  326. placesCreateSeparatorTransactions.prototype = {
  327.   __proto__: placesBaseTransaction.prototype,
  328.  
  329.   // childItemsTransaction support
  330.   get container() { return this._container; },
  331.   set container(val) { return this._container = val;clear },
  332.  
  333.   doTransaction: function PCST_doTransaction() {
  334.     this._id = PlacesUtils.bookmarks
  335.                           .insertSeparator(this.container, this._index);
  336.   },
  337.  
  338.   undoTransaction: function PCST_undoTransaction() {
  339.     PlacesUtils.bookmarks.removeChildAt(this.container, this._index);
  340.   }
  341. };
  342.  
  343. function placesCreateLivemarkTransactions(aFeedURI, aSiteURI, aName,
  344.                                           aContainer, aIndex,
  345.                                           aAnnotations) {
  346.   this._feedURI = aFeedURI;
  347.   this._siteURI = aSiteURI;
  348.   this._name = aName;
  349.   this._container = aContainer;
  350.   this._index = typeof(aIndex) == "number" ? aIndex : -1;
  351.   this._annotations = aAnnotations;
  352. }
  353.  
  354. placesCreateLivemarkTransactions.prototype = {
  355.   __proto__: placesBaseTransaction.prototype,
  356.  
  357.   // childItemsTransaction support
  358.   get container() { return this._container; },
  359.   set container(val) { return this._container = val; },
  360.  
  361.   doTransaction: function PCLT_doTransaction() {
  362.     this._id = PlacesUtils.livemarks.createLivemark(this._container, this._name,
  363.                                                     this._siteURI, this._feedURI,
  364.                                                     this._index);
  365.     if (this._annotations && this._annotations.length > 0)
  366.       PlacesUtils.setAnnotationsForItem(this._id, this._annotations);
  367.   },
  368.  
  369.   undoTransaction: function PCLT_undoTransaction() {
  370.     PlacesUtils.bookmarks.removeFolder(this._id);
  371.   }
  372. };
  373.  
  374. function placesMoveItemTransactions(aItemId, aNewContainer, aNewIndex) {
  375.   NS_ASSERT(aNewIndex >= -1, "invalid insertion index");
  376.   this._id = aItemId;
  377.   this._oldContainer = PlacesUtils.bookmarks.getFolderIdForItem(this._id);
  378.   this._oldIndex = PlacesUtils.bookmarks.getItemIndex(this._id);
  379.   NS_ASSERT(this._oldContainer > 0 && this._oldIndex >= 0, "invalid item");
  380.   this._newContainer = aNewContainer;
  381.   this._newIndex = aNewIndex;
  382.   this.redoTransaction = this.doTransaction;
  383. }
  384.  
  385. placesMoveItemTransactions.prototype = {
  386.   __proto__: placesBaseTransaction.prototype,
  387.  
  388.   doTransaction: function PMIT_doTransaction() {
  389.     PlacesUtils.bookmarks.moveItem(this._id, this._newContainer, this._newIndex);
  390.   },
  391.  
  392.   undoTransaction: function PMIT_undoTransaction() {
  393.     PlacesUtils.bookmarks.moveItem(this._id, this._oldContainer, this._oldIndex);
  394.   }
  395. };
  396.  
  397. function placesRemoveItemTransaction(aItemId) {
  398.   this.redoTransaction = this.doTransaction;
  399.   this._id = aItemId;
  400.   this._itemType = PlacesUtils.bookmarks.getItemType(this._id);
  401.   if (this._itemType == Ci.nsINavBookmarksService.TYPE_FOLDER) {
  402.     this._transactions = [];
  403.     this._removeTxn = PlacesUtils.bookmarks
  404.                                  .getRemoveFolderTransaction(this._id);
  405.   }
  406. }
  407.  
  408. placesRemoveItemTransaction.prototype = {
  409.   __proto__: placesBaseTransaction.prototype,
  410.  
  411.   doTransaction: function PRIT_doTransaction() {
  412.     this._oldContainer = PlacesUtils.bookmarks.getFolderIdForItem(this._id);
  413.     this._oldIndex = PlacesUtils.bookmarks.getItemIndex(this._id);
  414.     this._title = PlacesUtils.bookmarks.getItemTitle(this._id);
  415.     this._annotations = PlacesUtils.getAnnotationsForItem(this._id);
  416.  
  417.     if (this._itemType == Ci.nsINavBookmarksService.TYPE_FOLDER) {
  418.       this._saveFolderContents();
  419.  
  420.       // Remove children backwards to preserve parent-child relationships.
  421.       for (var i = this._transactions.length - 1; i >= 0; --i)
  422.         this._transactions[i].doTransaction();
  423.     
  424.       // Remove this folder itself. 
  425.       this._removeTxn.doTransaction();
  426.     }
  427.     else {
  428.       if (this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK)
  429.         this._uri = PlacesUtils.bookmarks.getBookmarkURI(this._id);
  430.       PlacesUtils.bookmarks.removeItem(this._id);
  431.     }
  432.   },
  433.  
  434.   undoTransaction: function PRIT_undoTransaction() {
  435.     if (this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK) {
  436.       this._id = PlacesUtils.bookmarks.insertBookmark(this._oldContainer,
  437.                                                       this._uri,
  438.                                                       this._oldIndex,
  439.                                                       this._title);
  440.     }
  441.     else if (this._itemType == Ci.nsINavBookmarksService.TYPE_FOLDER) {
  442.       this._removeTxn.undoTransaction();
  443.       // Create children forwards to preserve parent-child relationships.
  444.       for (var i = 0; i < this._transactions.length; ++i)
  445.         this._transactions[i].undoTransaction();
  446.     }
  447.     else // TYPE_SEPARATOR
  448.       PlacesUtils.bookmarks.insertSeparator(this._oldContainer, this._oldIndex);
  449.  
  450.     if (this._annotations.length > 0)
  451.       PlacesUtils.setAnnotationsForItem(this._id, this._annotations);
  452.   },
  453.  
  454.   /**
  455.   * Create a flat, ordered list of transactions for a depth-first recreation
  456.   * of items within this folder.
  457.   */
  458.   _saveFolderContents: function PRIT__saveFolderContents() {
  459.     this._transactions = [];
  460.     var contents =
  461.       PlacesUtils.getFolderContents(this._id, false, false).root;
  462.     for (var i = 0; i < contents.childCount; ++i) {
  463.       this._transactions
  464.           .push(new placesRemoveItemTransaction(contents.getChild(i).itemId));
  465.     }
  466.   }
  467. };
  468.  
  469. function placesEditItemTitleTransactions(id, newTitle) {
  470.   this._id = id;
  471.   this._newTitle = newTitle;
  472.   this._oldTitle = "";
  473.   this.redoTransaction = this.doTransaction;
  474. }
  475.  
  476. placesEditItemTitleTransactions.prototype = {
  477.   __proto__: placesBaseTransaction.prototype,
  478.  
  479.   doTransaction: function PEITT_doTransaction() {
  480.     this._oldTitle = PlacesUtils.bookmarks.getItemTitle(this._id);
  481.     PlacesUtils.bookmarks.setItemTitle(this._id, this._newTitle);
  482.   },
  483.  
  484.   undoTransaction: function PEITT_undoTransaction() {
  485.     PlacesUtils.bookmarks.setItemTitle(this._id, this._oldTitle);
  486.   }
  487. };
  488.  
  489. function placesEditBookmarkURITransactions(aBookmarkId, aNewURI) {
  490.   this._id = aBookmarkId;
  491.   this._newURI = aNewURI;
  492.   this.redoTransaction = this.doTransaction;
  493. }
  494.  
  495. placesEditBookmarkURITransactions.prototype = {
  496.   __proto__: placesBaseTransaction.prototype,
  497.  
  498.   doTransaction: function PEBUT_doTransaction() {
  499.     this._oldURI = PlacesUtils.bookmarks.getBookmarkURI(this._id);
  500.     PlacesUtils.bookmarks.changeBookmarkURI(this._id, this._newURI);
  501.   },
  502.  
  503.   undoTransaction: function PEBUT_undoTransaction() {
  504.     PlacesUtils.bookmarks.changeBookmarkURI(this._id, this._oldURI);
  505.   }
  506. };
  507.  
  508. function placesSetLoadInSidebarTransactions(aBookmarkId, aLoadInSidebar) {
  509.   this.id = aBookmarkId;
  510.   this._loadInSidebar = aLoadInSidebar;
  511.   this.redoTransaction = this.doTransaction;
  512. }
  513.  
  514. placesSetLoadInSidebarTransactions.prototype = {
  515.   __proto__: placesBaseTransaction.prototype,
  516.  
  517.   _anno: {
  518.     name: loadInSidebarAnno,
  519.     type: Ci.nsIAnnotationService.TYPE_INT32,
  520.     value: 1,
  521.     flags: 0,
  522.     expires: Ci.nsIAnnotationService.EXPIRE_NEVER
  523.   },
  524.  
  525.   doTransaction: function PSLIST_doTransaction() {
  526.     this._wasSet = PlacesUtils.annotations.itemHasAnnotation(this.id, this._anno.name);
  527.     if (this._loadInSidebar) {
  528.       PlacesUtils.setAnnotationsForItem(this.id, [this._anno]);
  529.     }
  530.     else {
  531.       try {
  532.         PlacesUtils.annotations.removeItemAnnotation(this.id, this._anno.name);
  533.       } catch(ex) { }
  534.     }
  535.   },
  536.  
  537.   undoTransaction: function PSLIST_undoTransaction() {
  538.     if (this._wasSet != this._loadInSidebar) {
  539.       this._loadInSidebar = !this._loadInSidebar;
  540.       this.doTransaction();
  541.     }
  542.   }
  543. };
  544.  
  545. function placesEditItemDescriptionTransactions(aItemId, aDescription) {
  546.   this.id = aItemId;
  547.   this._newDescription = aDescription;
  548.   this.redoTransaction = this.doTransaction;
  549. }
  550.  
  551. placesEditItemDescriptionTransactions.prototype = {
  552.   __proto__: placesBaseTransaction.prototype,
  553.  
  554.   _oldDescription: "",
  555.  
  556.   doTransaction: function PSLIST_doTransaction() {
  557.     const annos = PlacesUtils.annotations;
  558.     if (annos.itemHasAnnotation(this.id, descriptionAnno))
  559.       this._oldDescription = annos.getItemAnnotation(this.id, descriptionAnno);
  560.  
  561.     if (this._newDescription) {
  562.       annos.setItemAnnotation(this.id, descriptionAnno,
  563.                               this._newDescription, 0,
  564.                               annos.EXPIRE_NEVER);
  565.     }
  566.     else if (this._oldDescription)
  567.       annos.removeItemAnnotation(this.id, descriptionAnno);
  568.   },
  569.  
  570.   undoTransaction: function PSLIST_undoTransaction() {
  571.     const annos = PlacesUtils.annotations;
  572.     if (this._oldDescription) {
  573.       annos.setItemAnnotationString(this.id, descriptionAnno,
  574.                                     this._oldDescription, 0,
  575.                                     annos.EXPIRE_NEVER);
  576.     }
  577.     else if (annos.itemHasAnnotation(this.id, descriptionAnno))
  578.       annos.removeItemAnnotation(this.id, descriptionAnno);
  579.   }
  580. };
  581.  
  582. function placesEditBookmarkKeywordTransactions(id, newKeyword) {
  583.   this.id = id;
  584.   this._newKeyword = newKeyword;
  585.   this._oldKeyword = "";
  586.   this.redoTransaction = this.doTransaction;
  587. }
  588.  
  589. placesEditBookmarkKeywordTransactions.prototype = {
  590.   __proto__: placesBaseTransaction.prototype,
  591.  
  592.   doTransaction: function PEBKT_doTransaction() {
  593.     this._oldKeyword = PlacesUtils.bookmarks.getKeywordForBookmark(this.id);
  594.     PlacesUtils.bookmarks.setKeywordForBookmark(this.id, this._newKeyword);
  595.   },
  596.  
  597.   undoTransaction: function PEBKT_undoTransaction() {
  598.     PlacesUtils.bookmarks.setKeywordForBookmark(this.id, this._oldKeyword);
  599.   }
  600. };
  601.  
  602. function placesEditURIPostDataTransactions(aURI, aPostData) {
  603.   this._uri = aURI;
  604.   this._newPostData = aPostData;
  605.   this._oldPostData = null;
  606.   this.redoTransaction = this.doTransaction;
  607. }
  608.  
  609. placesEditURIPostDataTransactions.prototype = {
  610.   __proto__: placesBaseTransaction.prototype,
  611.  
  612.   doTransaction: function PEUPDT_doTransaction() {
  613.     this._oldPostData = PlacesUtils.getPostDataForURI(this._uri);
  614.     PlacesUtils.setPostDataForURI(this._uri, this._newPostData);
  615.   },
  616.  
  617.   undoTransaction: function PEUPDT_undoTransaction() {
  618.     PlacesUtils.setPostDataForURI(this._uri, this._oldPostData);
  619.   }
  620. };
  621.  
  622. function placesEditLivemarkSiteURITransactions(folderId, uri) {
  623.   this._folderId = folderId;
  624.   this._newURI = uri;
  625.   this._oldURI = null;
  626.   this.redoTransaction = this.doTransaction;
  627. }
  628.  
  629. placesEditLivemarkSiteURITransactions.prototype = {
  630.   __proto__: placesBaseTransaction.prototype,
  631.  
  632.   doTransaction: function PELSUT_doTransaction() {
  633.     this._oldURI = PlacesUtils.livemarks.getSiteURI(this._folderId);
  634.     PlacesUtils.livemarks.setSiteURI(this._folderId, this._newURI);
  635.   },
  636.  
  637.   undoTransaction: function PELSUT_undoTransaction() {
  638.     PlacesUtils.livemarks.setSiteURI(this._folderId, this._oldURI);
  639.   }
  640. };
  641.  
  642. function placesEditLivemarkFeedURITransactions(folderId, uri) {
  643.   this._folderId = folderId;
  644.   this._newURI = uri;
  645.   this._oldURI = null;
  646.   this.redoTransaction = this.doTransaction;
  647. }
  648.  
  649. placesEditLivemarkFeedURITransactions.prototype = {
  650.   __proto__: placesBaseTransaction.prototype,
  651.  
  652.   doTransaction: function PELFUT_doTransaction() {
  653.     this._oldURI = PlacesUtils.livemarks.getFeedURI(this._folderId);
  654.     PlacesUtils.livemarks.setFeedURI(this._folderId, this._newURI);
  655.     PlacesUtils.livemarks.reloadLivemarkFolder(this._folderId);
  656.   },
  657.  
  658.   undoTransaction: function PELFUT_undoTransaction() {
  659.     PlacesUtils.livemarks.setFeedURI(this._folderId, this._oldURI);
  660.     PlacesUtils.livemarks.reloadLivemarkFolder(this._folderId);
  661.   }
  662. };
  663.  
  664. function placesEditBookmarkMicrosummaryTransactions(aID, newMicrosummary) {
  665.   this.id = aID;
  666.   this._mss = Cc["@mozilla.org/microsummary/service;1"].
  667.               getService(Ci.nsIMicrosummaryService);
  668.   this._newMicrosummary = newMicrosummary;
  669.   this._oldMicrosummary = null;
  670.   this.redoTransaction = this.doTransaction;
  671. }
  672.  
  673. placesEditBookmarkMicrosummaryTransactions.prototype = {
  674.   __proto__: placesBaseTransaction.prototype,
  675.  
  676.   doTransaction: function PEBMT_doTransaction() {
  677.     this._oldMicrosummary = this._mss.getMicrosummary(this.id);
  678.     if (this._newMicrosummary)
  679.       this._mss.setMicrosummary(this.id, this._newMicrosummary);
  680.     else
  681.       this._mss.removeMicrosummary(this.id);
  682.   },
  683.  
  684.   undoTransaction: function PEBMT_undoTransaction() {
  685.     if (this._oldMicrosummary)
  686.       this._mss.setMicrosummary(this.id, this._oldMicrosummary);
  687.     else
  688.       this._mss.removeMicrosummary(this.id);
  689.   }
  690. };
  691.  
  692. function placesSortFolderByNameTransactions(aFolderId, aFolderIndex) {
  693.   this._folderId = aFolderId;
  694.   this._folderIndex = aFolderIndex;
  695.   this._oldOrder = null,
  696.   this.redoTransaction = this.doTransaction;
  697. }
  698.  
  699. placesSortFolderByNameTransactions.prototype = {
  700.   __proto__: placesBaseTransaction.prototype,
  701.  
  702.   doTransaction: function PSSFBN_doTransaction() {
  703.     this._oldOrder = [];
  704.  
  705.     var contents = PlacesUtils.getFolderContents(this._folderId, false, false).root;
  706.     var count = contents.childCount;
  707.  
  708.     // sort between separators
  709.     var newOrder = []; 
  710.     var preSep = []; // temporary array for sorting each group of items
  711.     var sortingMethod =
  712.       function (a, b) { return a.title.localeCompare(b.title); };
  713.  
  714.     for (var i = 0; i < count; ++i) {
  715.       var item = contents.getChild(i);
  716.       this._oldOrder[item.itemId] = i;
  717.       if (PlacesUtils.nodeIsSeparator(item)) {
  718.         if (preSep.length > 0) {
  719.           preSep.sort(sortingMethod);
  720.           newOrder = newOrder.concat(preSep);
  721.           preSep.splice(0);
  722.         }
  723.         newOrder.push(item);
  724.       }
  725.       else
  726.         preSep.push(item);
  727.     }
  728.     if (preSep.length > 0) {
  729.       preSep.sort(sortingMethod);
  730.       newOrder = newOrder.concat(preSep);
  731.     }
  732.  
  733.     // set the nex indexs
  734.     for (var i = 0; i < count; ++i)
  735.       PlacesUtils.bookmarks.setItemIndex(newOrder[i].itemId, i);
  736.   },
  737.  
  738.   undoTransaction: function PSSFBN_undoTransaction() {
  739.     for (item in this._oldOrder)
  740.       PlacesUtils.bookmarks.setItemIndex(item, this._oldOrder[item]);
  741.   }
  742. };
  743.  
  744. function placesSetBookmarksToolbarTransactions(aFolderId) {
  745.   this._folderId = aFolderId;
  746.   this.redoTransaction = this.doTransaction;
  747.   this._oldFolderId = PlacesUtils.bookmarks.toolbarFolder;
  748. }
  749.  
  750. placesSetBookmarksToolbarTransactions.prototype = {
  751.   __proto__: placesBaseTransaction.prototype,
  752.   doTransaction: function PSBTT_doTransaction() {
  753.     PlacesUtils.bookmarks.toolbarFolder = this._folderId;
  754.   },
  755.  
  756.   undoTransaction: function PSBTT_undoTransaction() {
  757.     PlacesUtils.bookmarks.toolbarFolder = this._oldFolderId;
  758.   }
  759. };
  760.  
  761. function NSGetModule(aCompMgr, aFileSpec) {
  762.   return XPCOMUtils.generateModule([placesTransactionsService]);
  763. }
  764.